import * as vscode from 'vscode';
import { SerialPort } from 'serialport';

export interface SerialPortInfo {
    path: string;
    manufacturer?: string;
    serialNumber?: string;
    pnpId?: string;
    locationId?: string;
    productId?: string;
    vendorId?: string;
}

export class SerialPortDiscovery {

    public static async listAvailablePorts(): Promise<SerialPortInfo[]> {
        try {
            const ports = await SerialPort.list();
            return ports.map(port => ({
                path: port.path,
                manufacturer: port.manufacturer,
                serialNumber: port.serialNumber,
                pnpId: port.pnpId,
                locationId: port.locationId,
                productId: port.productId,
                vendorId: port.vendorId
            }));
        } catch (error) {
            console.error('Failed to list serial ports:', error);
            return [];
        }
    }

    public static async showPortSelectionDialog(): Promise<string | undefined> {
        const ports = await this.listAvailablePorts();

        if (ports.length === 0) {
            vscode.window.showWarningMessage('No serial ports found. Please check your device connection.');
            return undefined;
        }

        const items = ports.map(port => ({
            label: port.path,
            description: this.getPortDescription(port),
            detail: this.getPortDetails(port),
            port: port
        }));

        const selected = await vscode.window.showQuickPick(items, {
            placeHolder: 'Select a serial port to connect to your MicroPython device',
            matchOnDescription: true,
            matchOnDetail: true
        });

        return selected?.port.path;
    }

    private static getPortDescription(port: SerialPortInfo): string {
        if (port.manufacturer) {
            return port.manufacturer;
        }
        return 'Unknown device';
    }

    private static getPortDetails(port: SerialPortInfo): string {
        const details: string[] = [];

        if (port.vendorId && port.productId) {
            details.push(`VID:${port.vendorId} PID:${port.productId}`);
        }

        if (port.serialNumber) {
            details.push(`S/N:${port.serialNumber}`);
        }

        return details.join(' | ');
    }

    public static isMicroPythonDevice(port: SerialPortInfo): boolean {
        // Common vendor IDs for MicroPython devices
        const micropythonVendorIds = [
            '239a', // Adafruit
            '2e8a', // Raspberry Pi
            '10c4', // Silicon Labs (ESP32)
            '1a86', // WCH (ESP32)
            '0403', // FTDI
            '067b'  // Prolific
        ];

        if (port.vendorId) {
            const vid = port.vendorId.toLowerCase();
            return micropythonVendorIds.some(id => vid.includes(id));
        }

        // Check by manufacturer name
        if (port.manufacturer) {
            const mfg = port.manufacturer.toLowerCase();
            return mfg.includes('micropython') ||
                   mfg.includes('circuitpython') ||
                   mfg.includes('adafruit') ||
                   mfg.includes('raspberry') ||
                   mfg.includes('espressif') ||
                   mfg.includes('silicon labs');
        }

        return false;
    }

    public static async findMicroPythonDevices(): Promise<SerialPortInfo[]> {
        const allPorts = await this.listAvailablePorts();
        return allPorts.filter(port => this.isMicroPythonDevice(port));
    }

    public static async autoDetectMicroPythonDevice(): Promise<string | undefined> {
        const micropythonPorts = await this.findMicroPythonDevices();

        if (micropythonPorts.length === 1) {
            return micropythonPorts[0].path;
        } else if (micropythonPorts.length > 1) {
            // Multiple devices found, show selection dialog
            const items = micropythonPorts.map(port => ({
                label: port.path,
                description: this.getPortDescription(port),
                detail: 'MicroPython device detected',
                port: port
            }));

            const selected = await vscode.window.showQuickPick(items, {
                placeHolder: 'Multiple MicroPython devices found. Please select one:',
                matchOnDescription: true
            });

            return selected?.port.path;
        }

        return undefined;
    }
}
